#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <assert.h>
#include <cstring>
#include <vector>
#include "Task.hpp"

using namespace std;
#define Debug

const int num = 5;
static int number = 1; //用于进程编号

class channel
{
public:
    channel(int fd, pid_t id):ctrlfd(fd), workerid(id)
    {
        name = "channel-" + to_string(number++);
    }
public:
    int ctrlfd; //文件描述符
    pid_t workerid; //子进程id
    string name; //管道名称   
};

void Work()
{
    while(true)
    {
        int code = 0;
        ssize_t n = read(0, &code, sizeof(code)); //规定每次读4个字节 
        assert(n != sizeof(code));
        (void)n; //防止编译器告警

        if(!init.CheckSafe(code)) continue; //判断任务码是否合法
        init.RunTask(code); //执行任务码为code的任务
    }
}

//创建信道
void CreateChannels(vector<channel>* c)
{
    for(int i = 0; i < num; i++)
    {
        //1.创建管道
        int pipefd[2] = {0};
        int n= pipe(pipefd);
        assert(n == 0);

        //2.创建进程
        pid_t id = fork();
        assert(id != -1);

        //3.构建单向通信信道
        if(0 == id)
        {
            //child
            close(pipefd[1]);
            dup2(pipefd[0], 0); //重定向，子进程从标准输入中读即可
            Work();
            exit(0);
        }

        //father
        close(pipefd[0]);
        c->push_back(channel(pipefd[1], id));
    }
}

void PrintDebug(const vector<channel>& c)
{
    for(const auto &channel : c)
    {
        cout << channel.name << ", " << channel.ctrlfd << ", " << channel.workerid << endl;
    }
}

int main()
{
    vector<channel> channels;
    //1.创建信道和进程
    CreateChannels(&channels);
    //PrintDebug(channels); 

    //2.开始完成任务
    int pos = 0;
    while(true)
    {
        //2.1选择任务
        int command = init.SelectTask();
        //2.2选择信道(进程)
        const auto &c = channels[pos++];
        pos %= channels.size();
        //2.3发送任务
        write(c.ctrlfd, &command, sizeof(command));
    }

    sleep(10);
    return 0;
}
